#ifndef HASHROW_H_JM_20120826
#define HASHROW_H_JM_20120826


#include <vector>
#include <functional>

namespace jmlib {

	enum HashRowActionCondition { HAS_KEY, HAS_NOT_KEY };

	template<class KeyT, class ValueT>
	class HashRow {
	public:
		
		/**
		* Typ ukladanych hodnot.
		**/
		
		typedef HashRow<KeyT, ValueT> HashRowInterface;

		typedef KeyT KeyType;
		typedef ValueT ValueType;

		struct RowEntry {
			RowEntry(const KeyType& k, const ValueType& v) : key(k), value(v) { }
			KeyType key;
			ValueType value;
		};

		class ExtendedRowEntry {
		public:
			ExtendedRowEntry(const KeyType& k, const ValueType& v) 
				: plainEntry(k, v), count(1) { }
			
			ExtendedRowEntry(const RowEntry& entry) 
				: plainEntry(entry) , count(1) { }
			
			size_t getCount() const { return count; }

			void setCount(size_t val) { 
				if (val > 1) 
					count = val; 
				else 
					count = val; 
			}

			RowEntry plainEntry;
		private:
			size_t count;
		};

		typedef std::function<void(RowEntry&)> ForechEntryFunType;
		typedef std::function<void(ExtendedRowEntry&)> ForechExtendedEntryFunType;

		//typedef void (*ForechFunType)(const RowEntry& entry);
		/**
		* Typ kontajneru pre vsetky hodnoty v riadku.
		**/
		typedef std::vector<ExtendedRowEntry> RowEntryContainer;

		/**
		* Pridanie hodnoty do riadku.
		* @param value hodnota pridavana do riadku
		**/
		virtual int add(const KeyType& key, const ValueType& value) = 0;
		virtual bool addIf(const KeyType& key, const ValueType& value,
			const HashRowActionCondition& cond) = 0;
		virtual bool hasKey(const KeyType& key) const  = 0;
		virtual bool remove(const KeyType& key) = 0;
		/**
		* Vrati hodnotu ulozenu v riadku na zadanom indexe.
		* @param index umiestenie pozadovanej hodnoty v riadku
		**/
		virtual ExtendedRowEntry getExtendedValue(const size_t& index) const = 0;

		/**
		* Je riadok prazdny?
		**/
		virtual bool isEmpty() const = 0;

		/**
		* Zmazanie vsetkych hodnot v riadku.
		**/
		virtual void clear() = 0;

		/**
		* Pocet rozsirenych zaznamov v riadku.
		* Nezohladnuje nasobnost zaznamu.
		**/
		virtual size_t getExtendedEntryCount() const = 0;
		virtual size_t getAggregatedEntryCount() const = 0;

		/// Vykonaj pre kazdy prvok riadku fun. ktora dostane ako parameter 
		/// ten prvok (jednoduchy format).
		virtual void foreach(ForechEntryFunType fun) = 0;
		/// Vykonaj pre kazdy prvok riadku fun. ktora dostane ako parameter 
		/// ten prvok (rozsireny format).
		virtual void foreachExtended(ForechExtendedEntryFunType fun) = 0;
		/// Vykonaj pre kazdy prvok riadku, ktory ma pozadovany kluc (hash 
		/// nezarucuje rozdielnost klucov), fun. ktora dostane ako parameter 
		/// ten prvok (jednoduchy format).
		/// @return true - aplikovalo sa, false - nebol najdeny ziaden prvok,
		/// na ktory by sa mohlo aplikovat

		virtual bool applyOn(ForechEntryFunType fun, const KeyType& key) = 0;
		/// Vykonaj pre kazdy prvok riadku, ktory ma pozadovany kluc (hash 
		/// nezarucuje rozdielnost klucov), fun. ktora dostane ako parameter 
		/// ten prvok (rozsireny format).
		/// @return true - aplikovalo sa, false - nebol najdeny ziaden prvok,
		/// na ktory by sa mohlo aplikovat
		virtual bool applyOnExtended(ForechExtendedEntryFunType fun, 
			const KeyType& key) = 0;

		virtual HashRowInterface* getLockFreeInstance() = 0;
		virtual HashRowInterface* getLockableInstance() = 0;

	};

} // namespace jmlib

#endif
